home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
macros
/
latex209
/
contrib
/
lgraph
/
lgraph.p
< prev
next >
Wrap
Text File
|
1993-01-11
|
18KB
|
458 lines
(**************************************************************************)
(* This program simulates a graph environment for LaTeX. Using a list of *)
(* parameters, it generates LaTeX commands to produce a complete graph. *)
(* see the latexgraph.doc file for detailed documentation. *)
(* author:Sunil Podar, podar@sbcs.csnet, ...!{allegra,philabs}!sbcs!podar *)
(* Please quote the following date when sending bug reports. *)
(* last update: Feb 2, 1987 (fixed bugs: wasn't doings things right when *)
(* (0,0) was not on the graph. Also removed the printing of *)
(* a few of the margin commands from preamble. *)
(* last update: Oct 5, 1986 *)
(**************************************************************************)
program main (input,output);
const delim = '@'; (* Latex never uses @ except for \@ for a little *)
(* space before a sentence-ending period *)
maxchar = 'F';(* maximum types of characters permitted for plotchar*)
(* A..F i.e. 6 distinct chars permitted *)
type wholeline = packed array[1..80] of char;
tenchar = packed array[1..10] of char;
ninechar = packed array[1..9] of char;
twochar = packed array[1..2] of char;
plotstufftype = record
chardef : wholeline;
charname : wholeline
end;
var
plotstuff : array['A'..maxchar] of plotstufftype;
error1,itsreal :boolean;
picwd,picht,pos,Xdeltabar,
Ydeltabar,i,Xlegloc,Ylegloc,Xdeltanum,Ydeltanum : integer;
Xaxisstrg,Yaxisstrg,capstring,blank80,labelname,fontname : wholeline;
legendloc,captiontwo,prepost : twochar;
string,blank10,captiontype,fignumber : tenchar;
plotchar,c : char;
string9 : ninechar;
Xscalegraph,Yscalegraph : integer;
XGorig,YGorig,XP1orig,YP1orig,XP2orig,YP2orig : integer;
Xscalereal,Yscalereal,xreality, yreality, xgraph, ygraph,
unitlngth,textwd,Xorignum,Yorignum,deln,num : real;
procedure strreadline(var commandstr: wholeline);
var charac:char;
i : integer;
endoffile, endofline:boolean;
begin
i:=1;
endoffile :=false;
endofline:=false;
commandstr:=blank80;
repeat
read(charac);
if (i < 80) then commandstr[i] := charac; (* 80th char remains @ *)
i := i+1;
if eof then endoffile :=true
else if eoln then endofline :=true
until (endoffile or endofline);
if (i <= 80) then commandstr[i] := delim;
if not endoffile then readln
end; (*strreadline*)
procedure strreadword(var string: tenchar; var string9: ninechar);
var charac:char;
i : integer;
begin
i:=1;
string:=blank10;
read(charac);
repeat
string[i] := charac;
read(charac);
i := i+1
until ((charac = '/') or (charac = ' ') or (i > 10) or eoln);
(* so I'm reading the / without assigning it to string, neat *)
if (eoln and (i <=10)) then string[i]:= charac;
(* a kluge, to capture the last charac when using this procedure to *)
(* read the argument. normally I use it only for parameters. *)
for i:= 1 to 9 do string9[i] := string[i]
end; (*strreadword*)
procedure strwrite(str: wholeline);
var i : integer;
begin
i := 1;
while (str[i] <> delim) do
begin
write(str[i]); i := i+1
end
end;
procedure legendread;
var i : integer;
temp : twochar;
begin
temp := ' ';
legendloc := ' '; i := 0;
if (not eoln) then
repeat
i := i+1; read(legendloc[i]);
until (eoln) or (i >= 2) or (legendloc[i] = '/');
if (not eoln) then if (legendloc[i] <> '/') then read(temp[1]);
if (temp[1] = '/') or (legendloc[i] = '/')
then readln(Xlegloc,Ylegloc)
else readln
end; (* legendread *)
(* in the following procedures, the boolean var XorY: true => X & false => Y*)
procedure putbars(XorY:boolean; Xpos, Ypos, deltabar, distance: integer);
var times: integer;
begin
times := distance div abs(deltabar);
if times > 0 then
if XorY (* X *)
then writeln('\multiput(',Xpos:1,',',Ypos:1,')(',
deltabar:1,',0){',times:1,'}{\line(0,1){2}}')
else writeln('\multiput(',Xpos:1,',',Ypos:1,')(0,',
deltabar:1,'){',times:1,'}{\line(1,0){2}}');
end; (* putbars *)
(* see a note about putnumbers in the main program. *)
(* because we may have real numbers, we can't use a counter *)
(* in conjunction with a \multiput statement. *)
procedure putnumbers(XorY:boolean; fixedpos, initpos:integer;
initnum, deln:real; deltanum:integer; limit:real);
var pos: integer;
num: real;
begin
num:=initnum; pos:= initpos;
if (abs(num) - round(abs(num) - 0.5)) > 0 then itsreal := true;
while abs(pos) < abs(limit) do
begin
if XorY then (* X *)
write('\put(',pos:1,',',fixedpos:1,'){\makebox(0,0)[t]{')
else write('\put(',fixedpos:1,',',pos:1,'){\makebox(0,0)[r]{');
if itsreal then writeln(num:1:2,'}}')
else writeln(trunc(num):1,'}}');
pos := pos + deltanum;
num := num + deln
end;
end; (* putnumbers *)
begin(* main *)
(*----------------------------------*)
(* Initializations & default values *)
(*----------------------------------*)
error1 := false;
itsreal:=false;
for i := 1 to 10 do blank10[i] := ' ';
for i := 1 to 79 do blank80[i] := ' '; blank80[80] := delim;
captiontype := blank10; captiontype := 'no '; (*default 'no' *)
fignumber := blank10;
fontname := blank80; (* just playing it safe *)
fontname := '{normalsize}'; fontname[13] := delim;
labelname := blank80; labelname[1] := 'n'; (* default 'no' *)
prepost := 'no';
unitlngth := 1.0;
picwd := 100; picht := 100; XP1orig := 0; YP1orig := 0;
legendloc := 'no';
Xscalegraph := 10; Xscalereal := 10;
Yscalegraph := 10; Yscalereal := 10;
Xdeltabar := 5; Xdeltanum := 10;
Ydeltabar := 5; Ydeltanum := 10;
Xorignum := 0;
Yorignum := 0;
for c := 'A' to maxchar do
begin
plotstuff[c].chardef[1] := 'n'; (* default value is 'no' *)
plotstuff[c].charname := blank80;
plotstuff[c].charname[1] := c;
plotstuff[c].charname[2] := delim
end;
Xlegloc := -999999;
Ylegloc := -999999;
strreadword(string, string9);
while string <> '%%%%%%%%%%' do
begin
if string = '%pre&post?' then readln(prepost[1])
else if string = '%unitlngth' then readln(unitlngth)
else if string = '%font-name' then strreadline(fontname)
else if string = '%picdimens' then readln(picwd,picht,XP1orig,YP1orig)
else if string = '%??caption' then begin
strreadword(captiontype, string9);
readln
end
else if string = '%fignumber' then begin
strreadword(fignumber, string9);
readln
end
else if string = '%Xaxisstrg' then strreadline(Xaxisstrg)
else if string = '%Yaxisstrg' then strreadline(Yaxisstrg)
else if string = '%capstring' then strreadline(capstring)
else if string = '%labelname' then strreadline(labelname)
else if string = '%legendloc' then legendread
else if string = '%Xdeltab:n' then readln(Xdeltabar,Xdeltanum)
else if string = '%Xoriginum' then readln(Xorignum)
else if string = '%Ydeltab:n' then readln(Ydeltabar,Ydeltanum)
else if string = '%Yoriginum' then readln(Yorignum)
else if string = '%Xratiog:r' then readln(Xscalegraph,Xscalereal)
else if string = '%Yratiog:r' then readln(Yscalegraph,Yscalereal)
else if string9 = '%plotchar' then
strreadline(plotstuff[string[10]].chardef)
else if string9 = '%plotname' then
strreadline(plotstuff[string[10]].charname)
else begin
readln;writeln;
writeln('**********************************************');
writeln('error: unknown string: "',string,'"');
writeln('**********************************************');
error1:=true
end;
string := blank10;
strreadword(string, string9)
end; (* while *)
readln; (* this readln is to finish reading the %%%%%.. line*)
(* THE FUN BEGINS HERE *)
if not error1 then
begin
textwd := picwd*unitlngth + 15.0; (* in mm *)
if (textwd < 170) then textwd := 170;
if textwd >240
then begin
writeln('% *****************************************************');
writeln('% max-possible-picwd is about 240mm which will have ');
writeln('% to be in Landscape. You''ll have to reduce scales.');
writeln('% *****************************************************')
end
else if textwd > 170 then
begin
writeln('% *****************************************************');
writeln('% THIS TEXT IS A BIT TOO WIDE FOR VERTICAL PAPER MODE.');
writeln('% YOU WILL HAVE TO USE LANDSCAPE MODE TO PRINT.');
writeln('% *****************************************************')
end;
if prepost[1] = 'y' then
begin
writeln('\documentstyle{article}');
writeln('\setlength{\textwidth}{',textwd:1:2,'mm}');
writeln('\pagestyle{empty} % => no page number ');
writeln('\begin{document}');
writeln;
end; (* end prepost *)
write('\newcommand{\xaxis}{'); strwrite(Xaxisstrg);
writeln('} % the literal for X-axis');
write('\newcommand{\yaxis}{'); strwrite(Yaxisstrg);
writeln('} % the literal for Y-axis');
c := 'A';
while (plotstuff[c].chardef[1] <> 'n') and (c <= maxchar) do
begin
write('\newcommand{\pchar',c,'}');
strwrite(plotstuff[c].chardef); writeln;
c := chr(ord(c) + 1)
end;
writeln;
write('\begin'); strwrite(fontname); writeln; (* fontname contains braces*)
writeln('\begin{figure}[p] %you might want different options here');
(* XGorig & YGorig refer to the origin of the graph. *)
(* XP1orig & YP1orig refer to the bottom-left origin of the picture box.*)
(* XP2orig & YP2orig refer to the bottom-right corner of the picture box.*)
(* see if (0,0) is on the graph or not *)
XGorig := 0; YGorig := 0;
if XP1orig >= 0 then XGorig := XP1orig
else if (picwd + XP1orig) < 0 then XGorig := XP1orig + picwd;
if YP1orig >= 0 then YGorig := YP1orig
else if (picht + YP1orig) < 0 then YGorig := YP1orig + picht;
XP2orig := picwd + XP1orig;
YP2orig := picht + YP1orig;
writeln('\unitlength = ',unitlngth:1:2,'mm');
writeln('\begin{center}');
writeln('\begin{picture}(',(picwd+10):1,',',(picht+10):1,')(',
(XP1orig-5):1,',',(YP1orig-5):1,')');
(* need a box of +10 on both axes to account for -10 origins & to *)
(* get proper centering *)
writeln('\thicklines');
(* plot the horizontal axis *)
if (XP2orig - XGorig) > 0 then
begin
writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(1,0){',
abs(XP2orig-XGorig):1,'}}');
writeln('\put(',(XP2orig+2):1,',',YGorig:1,'){\makebox(0,0)[l]{X}}')
end;
if (XGorig - XP1orig) > 0 then
begin
writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(-1,0){',
abs(XGorig-XP1orig):1,'}}');
writeln('\put(',(XP1orig-2):1,',',YGorig:1,
'){\makebox(0,0)[r]{X}}')
end;
(* plot the vertical axis *)
if (YP2orig - YGorig) > 0 then
begin
writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(0,1){',
abs(YP2orig-YGorig):1,'}}');
writeln('\put(',XGorig:1,',',(YP2orig+2):1,'){\makebox(0,0)[b]{Y}}')
end;
if (YGorig - YP1orig) > 0 then
begin
writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(0,-1){',
abs(YGorig-YP1orig):1,'}}');
writeln('\put(',XGorig:1,',',(YP1orig-2):1,
'){\makebox(0,0)[t]{Y}}')
end;
writeln('\thinlines');
(*********************************************************************)
(*the following put numbers & bars along X-axis and Y-axis *)
(*********************************************************************)
putbars(true,XGorig,(YGorig-1),Xdeltabar,abs(XP2orig-XGorig));
putbars(true,XGorig,(YGorig-1),-Xdeltabar,abs(XGorig-XP1orig));
putbars(false,(XGorig-1),YGorig,Ydeltabar,abs(YP2orig-YGorig));
putbars(false,(XGorig-1),YGorig,-Ydeltabar,abs(YGorig-YP1orig));
(* Before invoking putnumbers, we must explicitly check if it needs to
be invoked at all. This is because in the procedure putnumbers I use
absolute values as the stopping condition for while loop.
We use absolute values in the procedure so as to handle plotting
numbers on both the positive and negative halves of the axes.
deln below represents the delta graph units corresponding to X|Ydeltanum.
*)
writeln('% Add a line similar to next one if number at origin desired.');
deln := (Xscalereal*Xdeltanum) / Xscalegraph;
pos := XGorig + Xdeltanum; num:=Xorignum + deln;
if pos < XP2orig then
putnumbers(true,(YGorig-2),pos,num,deln,Xdeltanum,XP2orig);
pos := XGorig - Xdeltanum; num:=Xorignum - deln;
if pos > XP1orig then
putnumbers(true,(YGorig-2),pos,num,-deln,-Xdeltanum,XP1orig);
deln := ( Yscalereal*Ydeltanum) / Yscalegraph;
pos := YGorig + Ydeltanum; num:=Yorignum + deln;
if pos < YP2orig then
putnumbers(false,(XGorig-2),pos,num,deln,Ydeltanum,YP2orig);
pos := YGorig - Ydeltanum; num:=Yorignum - deln;
if pos > YP1orig then
putnumbers(false,(XGorig-2),pos,num,-deln,-Ydeltanum,YP1orig);
(***********************)
(* put the legend box *)
(***********************)
if (legendloc <> 'no') then
begin (* and if it is then obviously do nothing *)
if (Xlegloc = -999999) and (Ylegloc = -999999) then
begin (* implies explicit coordinates not specified *)
(* if they are then they are set in legendread *)
Xlegloc := picwd div 2; (* default is center *)
Ylegloc := picht div 2; (* default is center *)
if (legendloc[1] = 't') or (legendloc[2] = 't')
then if YP2orig > 0 then Ylegloc := picht else Ylegloc := picht-10;
if (legendloc[1] = 'b') or (legendloc[2] = 'b')
then if YP1orig >= 0 then Ylegloc := 10 else Ylegloc := 0;
if (legendloc[1] = 'l') or (legendloc[2] = 'l')
then if XP1orig >= 0 then Xlegloc := 10 else Xlegloc := 0;
if (legendloc[1] = 'r') or (legendloc[2] = 'r')
then if XP2orig > 0 then Xlegloc := picwd else Xlegloc := picwd-10;
Xlegloc := Xlegloc + XP1orig;
Ylegloc := Ylegloc + YP1orig
end;
write('\put(',Xlegloc:1,',',Ylegloc:1,'){\makebox(0,0)');
i:= 1; write('[');
while (i <= 2) do
begin
if (legendloc[i] <> ' ') and (legendloc[i] <> '/') then
write(legendloc[i]);
i:=i+1
end;
write(']');
writeln('{\fbox{\shortstack[l]{');
c:='A';
while (plotstuff[c].chardef[1] <> 'n') and (c <= maxchar) do
begin
write(' {\makebox(4,2)[lb]{\put(2,1){\pchar',c,'}}}: ');
strwrite(plotstuff[c].charname); writeln('\\');
c := chr(ord(c) + 1)
end;
writeln(' {\makebox(4,4)[b]{X}}: \xaxis \\');
writeln(' {\makebox(4,2)[b]{Y}}: \yaxis');
writeln(' }}}}')
end; (* not 'no' of legendloc*)
(* put the caption if explicit *)
captiontwo[1]:=capstring[1];
captiontwo[2]:=capstring[2];
if captiontype[1] = 'e' then (* "e"xplicit, anything else other than *)
(* "L" for LaTeX => no *)
if captiontwo = 'YX' then
begin
writeln('% if the caption line is longer than the graphwidth, comment');
writeln('% out the second line and use first one. you might have to');
writeln('% fiddle with the width of parbox in the second stmt.');
write('%\put(',XP1orig:1,',',(YP1orig-18):1,
'){\makebox(',picwd:1,',0)[tl]{');
writeln('Figure ',fignumber,'$\!$: \parbox[t]{',(textwd-32):1:1,'mm}{%');
write('\put(',XP1orig:1,',',(YP1orig-18):1,
'){\makebox(',picwd:1,',0)[t]{');
writeln('Figure ',fignumber,'$\!$: {%');
writeln('%\yaxis\ vs.\ \xaxis}}}')
end
else (* means explicit string is specified *)
begin
write('%\put(',XP1orig:1,',',(YP1orig-18):1,
'){\makebox(',picwd:1,',0)[tl]{');
writeln('Figure ',fignumber,'$\!$: \parbox[t]{',(textwd-32):1:1,'mm}{%');
write('\put(',XP1orig:1,',',(YP1orig-18):1,
'){\makebox(',picwd:1,',0)[t]{');
writeln('Figure ',fignumber,'$\!$: {%');
strwrite(capstring); writeln;
writeln('}}}');
end;
writeln('% beginning of data');
while not eof do
begin
readln(plotchar,xreality,yreality);
xgraph := (xreality*Xscalegraph)/Xscalereal;
ygraph := (yreality*Yscalegraph)/Yscalereal;
writeln('\put(',xgraph:1:5,',',ygraph:1:5,'){\pchar',plotchar,'}')
end;
writeln('% end of data');
writeln('\end{picture}');
writeln('\end{center}');
(* put the LaTeX \caption if so specified *)
if captiontype[1] = 'L' then (* "L"aTeX . if it is not = 'L' or 'e'*)
(* then interpreted as 'no' *)
begin
writeln('% if the caption line is longer than the graphwidth,use a');
writeln('% \parbox[t]{...mm}{.......} like statement for the argument');
writeln('% with suitable args for parbox to get things centered.');
if captiontwo = 'YX'
then begin
writeln('% You might want to add a [] to \caption below.');
writeln('\caption{\protect\normalsize \yaxis\ vs.\ \xaxis }')
end
else begin
writeln('\caption{\protect\normalsize ');
strwrite(capstring); writeln;
writeln('}')
end;
if labelname[1] = '{' then (* anything else => 'no' *)
begin
write('\label'); strwrite(labelname); writeln
(* labelname contains the braces *)
end
end;
writeln('\end{figure}');
writeln; (* a blank line is supposedly needed before \end fontname *)
(* so says the latex manual *)
write('\end'); strwrite(fontname); writeln; (* fontname contains braces *)
writeln;
if prepost[1] = 'y' then
writeln('\end{document}');
end (* not error1 *)
end.